const PENDING = "pending";	//等待
const FULFILLED = "fulfilled"	//成功
const REJECTED = "rejected"	//失败
class MyPromise{
	constructor(exec){
		// 捕获执行器错误
		try{
			exec(this.resolve, this.reject)
		} catch (e){
			this.reject(e);
		}
		
	}
	//promise 状态。默认：等待
	status = PENDING;
	//成功之后的值
	value = undefined;
	//失败之后的原因
	reason = undefined;
	// 成功回调 数组同时存贮多个回调函数
	successCallback = [];
	// 失败回调
	failCallback = [];

	resolve = value => {
		//如果状态不是等待 阻止程序向下执行
		if(this.status !== PENDING) return;
		//将状态改为 成功
		this.status = FULFILLED;
		//保存成功的值
		this.value = value;
		// 判断成功回调是否存在 如果存在调用
		//this.successCallback && this.successCallback(this.value)
		while (this.successCallback.length) this.successCallback.shift()();
	}
	
	reject = reason => {
		//如果状态不是等待 阻止程序向下执行
		if(this.status !== PENDING) return;
		//将状态改为 失败
		this.status = REJECTED;
		//保存失败的原因
		this.reason = reason;
		// 判断失败回调是否存在 如果存在调用
		//this.failCallback && this.failCallback(this.reason)
		while (this.failCallback.length) this.failCallback.shift()();
	}
	
	then(successCallback, failCallback){
		successCallback = successCallback ? successCallback : value=>value;
		failCallback = failCallback ? failCallback : reason=> {throw reason};
		let promise2 = new MyPromise((resolve, reject) => {
			//判断状态
			if (this.status === FULFILLED){
				// 异步是为了获取promise2
				setTimeout(() => {
					try{
						let x = successCallback(this.value);
						//resolve(x);	//传递给下一个then
						// 判断 x 的值是普通值还是promise对象
						// 如果是普通值 直接调用resolve
						// 如果是promise对象 查看promise对象返回结果
						// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
						resolvePromise( promise2, x, resolve, reject)
					}catch (e){
						reject(e)
					}
				}, 0);
				
			}else if(this.status === REJECTED){
				
				// 异步是为了获取promise2
				setTimeout(() => {
					try{
						let x = failCallback(this.reason);
						//resolve(x);	//传递给下一个then
						// 判断 x 的值是普通值还是promise对象
						// 如果是普通值 直接调用resolve
						// 如果是promise对象 查看promise对象返回结果
						// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
						resolvePromise( promise2, x, resolve, reject)
					}catch (e){
						reject(e)
					}
				}, 0);
			}else{
				// 等待
				// 将成功回调和失败回调存储起来
				this.successCallback.push(() => {
					setTimeout(() => {
						try{
							let x = successCallback(this.value);
							//resolve(x);	//传递给下一个then
							// 判断 x 的值是普通值还是promise对象
							// 如果是普通值 直接调用resolve
							// 如果是promise对象 查看promise对象返回结果
							// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
							resolvePromise( promise2, x, resolve, reject)
						}catch (e){
							reject(e)
						}
					}, 0);
				});
				this.failCallback.push(()=>{
					setTimeout(() => {
						try{
							let x = failCallback(this.reason);
							//resolve(x);	//传递给下一个then
							// 判断 x 的值是普通值还是promise对象
							// 如果是普通值 直接调用resolve
							// 如果是promise对象 查看promise对象返回结果
							// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
							resolvePromise( promise2, x, resolve, reject)
						}catch (e){
							reject(e)
						}
					}, 0);
				});
			};
		});
		
		// 返回promise 实现链式调用
		return promise2;
	}

	finally(callback){
		return this.then( value => {
			// callback();
			// return value;
			return MyPromise.resolve(callback()).then(() => value)
		},reason => {
			// callback();
			// throw reason;
			return MyPromise.resolve(callback()).then(() => {throw reason})
		})
	}

	catch(failCallback){
		return this.then(undefined, failCallback)
	}

	static all(array){
		// 结果数组
		let result = [];
		let index = 0;
		
		return new MyPromise((resolve,reject)=>{
			function addData(key, value){
				result[key] = value;
				index++;
				if(index === array.length){
					resolve(result);
				}
			}
			for( let i = 0; i < array.length; i++){
				// 当前值
				let current = array[i];
				if(current instanceof MyPromise){
					// promise对象
					current.then(
						value => addData(i,value),
						reason => reject(reason)
					)
				}else{
					// 普通值
					addData(i,array[i])
				}
			}
			
		})
	}

	static resolve(value){
		if( value instanceof MyPromise) return value;
		return new MyPromise(resolve => resolve(value))
	}
}

function resolvePromise(promise2, x, resolve, reject){
	if(promise2 === x) {
		return reject(new TypeError("循环调用pormoise"))
	}
	if(x instanceof MyPromise){
		//promise对象 查看状态 将状态传给下一个promise对象
		//x.then( value => resolve(value), reason => reject(reason))
		x.then(resolve , reject)
	}else{
		// 普通值
		resolve(x)
	}
}

module.exports = MyPromise;
